package com.keepc.licence.util;

import de.schlichtherle.license.*;
import lombok.extern.slf4j.Slf4j;

import java.text.DateFormat;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.concurrent.TimeUnit;
import java.util.prefs.Preferences;

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;

import com.keepc.licence.entity.LicenseVerifyParam;
import com.keepc.licence.serverinfo.CustomKeyStoreParam;

@Slf4j
public class LicenseVerify {

    private static final String CACHE_KEY_LICENSE_CHECK_RESULT = "license_check_result";

    private static final Cache<Object, Object> cache = Caffeine.newBuilder()
            // 初始数量
            .initialCapacity(10)
            // 最大条数
            .maximumSize(10)
            // PS：expireAfterWrite和expireAfterAccess同时存在时，以expireAfterWrite为准。
            // 最后一次写操作后经过指定时间过期
            .expireAfterWrite(3, TimeUnit.MINUTES)
            // 监听缓存被移除
            .removalListener((key, val, removalCause) -> {
            })
            // 记录命中
            .recordStats()
            .build();

    /**
     * 安装License证书
     */
    public synchronized void install(LicenseVerifyParam param) {
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 1. 安装证书
        try {
            LicenseManager licenseManager = LicenseManagerHolder.getInstance(initLicenseParam(param));
            licenseManager.uninstall();
            LicenseContent result = licenseManager.install(FileUtils.getFile(param.getLicensePath()));
            log.info(MessageFormat.format("证书安装成功，证书有效期：{0} - {1}", format.format(result.getNotBefore()),
                    format.format(result.getNotAfter())));
        } catch (Exception e) {
            log.error("证书安装失败！", e);
        }
    }

    /**
     * 校验License证书
     * 
     * @return boolean
     */
    public boolean verify() {
        Object cacheVal = cache.getIfPresent(CACHE_KEY_LICENSE_CHECK_RESULT);
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if (cacheVal != null) {
            log.info("读取到缓存数据........");
            LicenseContent licenseContent = (LicenseContent) cacheVal;
            log.info(MessageFormat.format("证书校验通过，证书有效期：{0} - {1}", format.format(licenseContent.getNotBefore()),
                    format.format(licenseContent.getNotAfter())));
            return true;
        }
        LicenseManager licenseManager = LicenseManagerHolder.getInstance(null);
        // 2. 校验证书
        try {
            LicenseContent licenseContent = licenseManager.verify();
            cache.put(CACHE_KEY_LICENSE_CHECK_RESULT, licenseContent);
            log.info(MessageFormat.format("证书校验通过，证书有效期：{0} - {1}", format.format(licenseContent.getNotBefore()),
                    format.format(licenseContent.getNotAfter())));
            return true;
        } catch (Exception e) {
            log.error("证书校验失败！", e);
            return false;
        }
    }

    /**
     * 初始化证书生成参数
     * 
     * @param param License校验类需要的参数
     * @return de.schlichtherle.license.LicenseParam
     */
    private LicenseParam initLicenseParam(LicenseVerifyParam param) {
        Preferences preferences = Preferences.userNodeForPackage(LicenseVerify.class);
        CipherParam cipherParam = new DefaultCipherParam(param.getStorePass());
        KeyStoreParam publicStoreParam = new CustomKeyStoreParam(LicenseVerify.class,
                param.getPublicKeysStorePath(), param.getPublicAlias(), param.getStorePass(), null);
        return new DefaultLicenseParam(param.getSubject(), preferences, publicStoreParam, cipherParam);
    }
}